// ==UserScript==
// @name           Yphotoalbum
// @namespace      http://tsuyuguchi.com/
// @include        http://album.yahoo.co.jp/*
// ==/UserScript==

/*** Change Logs *****************************/
/*
version: 0.0.9
	- 2008/05/14 show flickr icon in masthead
version: 0.0.8
	- 2008/05/14 reload after id tie setting changed
version: 0.0.7
	- 2008/05/14 show msg when flickr photos|sets is empty.
version: 0.0.6
	- 2008/04/17 support video thumbnails
version: 0.0.5
	- 2008/04/09 change internal stored data handling
version: 0.0.4
	- 2008/04/08 show friends' flickr account on http://album.yahoo.co.jp/friends/*
version: 0.0.3
	- 2008/04/08 change Xpath from which value of friend_key is got.
version: 0.0.2
	- 2008/04/07 some bugs fixed
version: 0.0.1
	- 2008/04/05 initial version
*/

(function(){

	/****** Config ***********************/
	// Tab
	var tab_config = [
		{ txt : "Flickr",
		  url : function(){ return "http://www.flickr.com/photos/"+user_id+"/"; }
		},
		{ txt : "Contact List",
		  url : function(){ return "http://www.flickr.com/people/"+user_id+"/contacts/"; }
		},
		null
	];

	/****** Global Variables *************/
	var yid = "";
	var api_key = "";
	var user_id = "";
	var username = "";
	var friend_key = "";
	var friend_id = "";
	var friend_username = "";
	var now_url = location.href;

	/****** Const ************************/
	var flickr_entrypoint = "http://api.flickr.com/services/rest/?";
	
	/****** functions called as JSONP CallBack *********************/
	var setUserId = function( obj ){
		if( obj.code ){
			if( obj.code == 100 ){
				error_api_key_invalid();
			}
			if( obj.code == 1 ){
				alert( "'"+username+"' is not found in Flickr");
				userinfo.clear('username');
				userinfo.write();
			}
			return;
		}
		user_id = obj.user.id;
		userinfo.set( 'user_id', user_id );
		userinfo.write();
	}
	var setFriendUserId = function( obj ){
		if( obj.code ){
			if( obj.code == 100 ){
				error_api_key_invalid();
			}
			if( obj.code == 1 ){
				alert( "'"+friend_username+"' is not found in Flickr");
				friendinfo.clear(friend_key);
				friendinfo.write();
			}
			return;
		}
		friend_id = obj.user.id;
		friendinfo.set( friend_key, 'id', friend_id );
		friendinfo.set( friend_key, 'username', friend_username );
		friendinfo.write();
		var profile_name = findElementsByXpath('//div[@id="yahooIdentityUserCard"]/div[@class="roundCornerBox"]/div[@class="roundCornerMiddle"]'
		                                        + '/div[@class="roundCornerBox"]/div[@class="roundCornerMiddle"]/div[@class="yahooIdentityUserCardContents"]'
		                                        + '/span[@class="yahooIdentityUserCardTitle"]').snapshotItem(0).innerHTML;
		profile_name = profile_name.replace( /<wbr>/g, '' );
		alert( '"' + profile_name + '" と Flickr id:' + friend_username + ' を連携させました。' );
		location.reload();
	}
		
	var showContactPhotos = function( obj ){
		if( obj.code == 100 ){
			error_api_key_invalid();
			return;
		}
		var div = document.getElementById('flickrcontactphoto');
		var panel = genTopPageContainer( div, 'Flickr Contacts Photos', 'http://www.flickr.com/photos/friends/' );
		var photos = obj.photos.photo;
		var len = photos.length;
		for( var i = 0; i < len; i++ ){
			var node = createPhotoPanel( photos[i], i == len - 1 );
			panel.appendChild( node );
		}
	}

	var showInterestingness = function( obj ){
		if( obj.code == 100 ){
			error_api_key_invalid();
			return;
		}
		var div = document.getElementById('flickrinterestingness');
		var panel = genTopPageContainer( div, 'Flickr Interestingness', 'http://www.flickr.com/explore/interesting/' );
		var photos = obj.photos.photo;
		var len = photos.length;
		for( var i = 0; i < len; i++ ){
			var node = createPhotoPanel( photos[i], i == len - 1 );
			panel.appendChild( node );
		}
	}
	
	var showFlickrPhotos = function( obj ){
		if( obj.code == 100 ){
			error_api_key_invalid();
			return;
		}
		var div = document.getElementById('flickrphotos');
		var photos = obj.photos.photo;
		var len = photos.length;
		if( len == 0 ){
			genEmptyContainer( div, 'Flickr Photo', 'Flickr Photo はありません。' );
			return;
		}
		var panel = genTopPageContainer( div, 'Flickr Photo', genUserTopUrl( friend_id || user_id ) );
		for( var i = 0; i < len; i++ ){
			var node = createPhotoPanel( photos[i], i == len - 1, true );
			panel.appendChild( node );
		}
	};
	
	var showFlickrSets = function( obj ){
		if( obj.code == 100 ){
			error_api_key_invalid();
			return;
		}
		var div = document.getElementById('flickrsets');
		var photosets = obj.photosets.photoset;
		var len = photosets.length < 5 ? photosets.length : 5
		if( len == 0 ){
			genEmptyContainer( div, 'Flickr Sets', 'Flickr Set はありません。' );
			return;
		}
		var panel = genTopPageContainer( div, 'Flickr Sets', genUserSetListPage( friend_id || user_id ) );
		for( var i = 0; i < len; i++ ){
			var node = createPhotoSetPanel( photosets[i], i == len - 1, true );
			panel.appendChild( node );
		}
	}
	
	var showFlickrContact = function( obj ){
		var node = findElementsByXpath('//div[@id="yahooIdentityContactBadge"]/div[@class="yahooIdentityContactBadgeBGtop"]/div[@class="yahooIdentityContactBadgePanelRow clearFix"]').snapshotItem(0);
		if( obj.contacts.total == 0 ){ // no contacts
			return;
		}
		var contacts = obj.contacts.contact;
		var len = contacts.length;
		var div = createNode('div');
		var rowcontainer = null;
		for( var i = 0; i < len; i++ ){
			var icon = genContactIcon( contacts[i], i%3 == 2 );
			if( i%3 == 0 )
				rowcontainer = createNode('div','yahooIdentityContactBadgePanelRow clearFix');
			rowcontainer.appendChild( icon );
			if( i%3 == 2 || i == len - 1 )
				div.appendChild( rowcontainer );
		}
		node.parentNode.insertBefore( div, node );
		var node = findElementsByXpath('//div[@id="yahooIdentityContactBadge"]/div[@class="yahooIdentityContactBadgeBGtop"]/div[@class="yahooIdentityContactBadgeTitle"]').snapshotItem(0);
		node.innerHTML += '<span class="yahooIdentityContactBadgeTitleLink">（Flickr:'+obj.contacts.total+'人）</span>';
		var node = findElementsByXpath('//div[@id="yahooIdentityContactBadge"]/div[@class="yahooIdentityContactBadgeBGtop"]/div[@class="yahooIdentityContactBadgeSeeAll"]').snapshotItem(0);
		node.innerHTML += '<br />' + createSeeAll( genContactListPageUrl( friend_id || user_id ), 'Flickr Contacts' );
	}

	/****** Common Functions *************/
	var showFlickrMasthead = function(){
		var node = findElementsByXpath('//div[@class="yjmthproplogoarea"]').snapshotItem(0);
		node.innerHTML += '<span style="font-weight:bold;vertical-align:bottom;font-size:smaller;">meets</span> <a href="http://flickr.com"><img src="http://l.yimg.com/www.flickr.com/images/flickr_logo_gamma.gif.v35314.14" /></a>';
	}
	
	var createTab = function(){
		var node = findElementsByXpath('//div[@id="header"]/div[@class="navigationMain"]/div[@class="navigationTab"]').snapshotItem(0);
		for( var i = 0; tab_config[i]; i++ ){
			var txt = tab_config[i].txt;
			txt = (typeof(txt) == 'function') ? txt() : txt;
			var url = tab_config[i].url;
			url = (typeof(url) == 'function') ? url() : url;
			var left = createNode('div', 'navigationLeft');
			var center = createNode('div', 'navigationCenter');
			center.innerHTML = '<a href="'+url+'">'+txt+'</a>';
			var right = createNode('div', 'navigationRight');
			node.appendChild(left);
			node.appendChild(center);
			node.appendChild(right);
		}
	};
	
	var createPhotoPanel = function( photoObj, isLast, isPreferTitle ){
		var panel = createNode('div', isLast ? 'panelContainerRight':'panelContainer' );
		var photo = createNode('span', 'photoContainer');
		var name = createNode('span', 'nameContainer');
		var owner = photoObj.owner;
		var username = photoObj.username;
		var title = photoObj.title;
		var media = photoObj.media;

		if( media == 'photo' ){
			photo.innerHTML = '<a href="'+genPhotoPageUrl(photoObj)+'"><img title="'+title+'" src="'+genPhotoThumbnailUrl(photoObj)+'" /></a>';
		}
		else{ // video
			photo.innerHTML = genVideoThumbnailUrl(photoObj);
		}
		
		if( isPreferTitle && title ){
			name.innerHTML = '<a href="'+genPhotoPageUrl(photoObj)+'">'+title+'</a>';
		}
		else if( username ){
			name.innerHTML = '<a href="'+genUserTopUrl( owner )+'">'+username+'</a>';
		}
		else if( owner ){
			name.innerHTML = '<a href="'+genUserTopUrl( owner )+'">'+owner+'</a>';
			var url = flickr_entrypoint + "method=flickr.people.getInfo"
			          + "&api_key="+api_key+"&user_id="+owner+"&format=json&nojsoncallback=1";
			GM_xmlhttpRequest( genHttpRequestObj( url, genFuncToShowUserName(name) ) );

		}
		panel.appendChild( photo );
		panel.appendChild( name );
		return panel;
	}

	var createPhotoSetPanel = function( photosetObj, isLast, isPreferTitle ){
		var panel = createNode('div', isLast ? 'panelContainerRight':'panelContainer' );
		var photo = createNode('span', 'photoContainer');
		var name = createNode('span', 'nameContainer');
		var title = photosetObj.title._content;
		photo.innerHTML = '<a href="'+genPhotoSetUrl(photosetObj, friend_id || user_id )+'"><img title="'+title+'" src="'+genPhotoSetThumbnailUrl(photosetObj)+'" /></a>';
		name.innerHTML = '<a href="'+genPhotoSetUrl(photosetObj, friend_id || user_id )+'">'+title+'</a>';
		panel.appendChild( photo );
		panel.appendChild( name );
		return panel;
	}
	
	var genContactIcon = function( contactObj, isLast ){
		var container = createNode('div', isLast ? 'yahooIdentityContactBadgePanelContainerRightend':'yahooIdentityContactBadgePanelContainer');
		var panel = createNode('div', 'yahooIdentityContactBadgePanel' );
		var name = createNode('div', 'clearFix' );
		var id = contactObj.nsid;
		panel.innerHTML = '<table><tbody><tr><td><div>'
		                  + '<a href="'+genUserTopUrl(id)+'"><img src="'+genContactIconImgUrl(contactObj)+'" /></a>';
		                  + '</div></td></tr></tbody></table>';
		name.innerHTML = '<a href="'+genUserTopUrl(id)+'">'+contactObj.username+'</a>';
		container.appendChild( panel );
		container.appendChild( name );
		return container;
	}
	
	var genEmptyContainer = function( div, title, msg ){
		var title = createNode('div', 'title', '<h1>'+title+'</h1>');
		var empty = createNode('div', 'emptyBox', msg );
		div.appendChild( title );
		div.appendChild( empty );
	}
	
	var genTopPageContainer = function( div, title, all_url ){
		var title = createNode('div', 'title', '<h1>'+title+'</h1>');
		var container = createNode('div', 'containerDot');
		var panel = createNode('div', 'panelRow clearFix');
		var seeall = createNode('div', 'seeAll', createSeeAll( all_url ) );
		div.appendChild( title );
		div.appendChild( container );
		container.appendChild( panel );
		div.appendChild( seeall );
		return panel;
	}

	var genFuncToShowUserName = function( node ){
		return function( res ){
			if( res.status != 200 ) return;
			var userinfo = eval( '(' + res.responseText + ')' );
			var username = userinfo.person.username._content;
			var url = userinfo.person.photosurl._content;
			node.innerHTML =  '<a href="'+url+'">'+username+'</a>';
		}
	}
	
	/****** Utility Functions ************/
	var findElementsByXpath = function( xpath ){
			return document.evaluate( xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	}
	
	var getYid = function(){
		var node = findElementsByXpath( '//div[@id="masthead"]/div[@class="yjmth"]/div[@class="yjmthloginarea"]/strong' ).snapshotItem(0);
		var txt = node.innerHTML;
		return txt.match( /^[_a-zA-Z0-9]+$/ ) ? txt : "";
	}

	/******* DOM Utility function ********************/
	var createNode = function( tag, class, innerHTML ){
		var node = document.createElement(tag);
		if( class ){
			node.setAttribute('class', class);
		}
		if( innerHTML ){
			node.innerHTML = innerHTML;
		}
		return node;
	}

	var createSeeAll = function( url, txt ){
		if( !txt ) txt = '一覧';
		return '<a href="'+url+'"><img src="http://i.yimg.jp/images/socialproducts/common/seeAll_14.gif" alt="一覧" width="14" height="14"></a><a href="'+url+'">'+txt+'</a>';
	}

	/****** Error Handling functions ****************/
	var error_api_key_invalid = function(){
		alert( "Flickr api key is invalid");
		userinfo.clear('api_key');
		userinfo.write();
	}

	/****** GM storage utility functions ***********/
	var userinfo = {
		_hash : {},
		_init : false,
		_dirty : false,
		_initialize : function(){
				this._read();
				this._init = true;
		},
		_read : function(){
			if( !this._dirty ){
				this._hash = eval("("+GM_getValue("_hash")+")") || {};
			}
		},
		write : function(){
			if( this._dirty ){
				GM_setValue( "_hash", this._hash.toSource() );
				this._dirty = false;
			}
		},
		set : function( key, value ){
			var initialize = false;
			if( !this._init ){
				this._initialize();
				initialize = true;
			}
			if( !value )
				delete this._hash[key];
			else
				this._hash[key] = value;
			this._dirty = true;
		},
		get : function( key ){
			if( !this._init ){
				this._initialize();
			}
			return this._hash[key];
		},
		clear : function( key ){
			if( !this._init ){
				this._initialize();
			}
			this.set(key, null);
		}
	};
	var friendinfo = {
		_hash : {},
		_init : false,
		_dirty : false,
		_initialize : function(){
				this._read();
				this._init = true;
		},
		_read : function(){
			if( !this._dirty ){
				this._hash = eval("("+GM_getValue("_friend")+")") || {};
			}
		},
		write : function(){
			if( this._dirty ){
				GM_setValue( "_friend", this._hash.toSource() );
				this._dirty = false;
			}
		},
		set : function( friend_key, key, value ){
			var initialize = false;
			if( !this._init ){
				this._initialize();
				initialize = true;
			}
			if( !this._hash[friend_key] )
				this._hash[friend_key] = {};
			if( !key && this._hash[friend_key] )
				delete this._hash[friend_key];
			else if( !value )
				delete this._hash[friend_key][key];
			else
				this._hash[friend_key][key] = value;
			if( !initialize )
				this._dirty = true;
		},
		get : function( friend_key, key ){
			if( !this._init ){
				this._initialize();
			}
			if( key == null ){
				return this._hash[friend_key];
			}
			return this._hash[friend_key] ? this._hash[friend_key][key] : null;
		},
		clear : function( friend_key, key ){
			if( !this._init ){
				this._initialize();
			}
			if( key )
				this.set(friend_key, key, null);
			else
				this.set(friend_key, null, null);
		}
	};


	/**** Flickr utility functions *********************************************/
	var genPhotoThumbnailUrl = function( photoObj ){
		return 'http://farm'+photoObj.farm+'.static.flickr.com/'+photoObj.server+'/'+photoObj.id+'_'+photoObj.secret+'_t.jpg';
	}
	var genVideoThumbnailUrl = function( photoObj ){
		var secret = photoObj.secret;
		var id = photoObj.id;
		return '<object type="application/x-shockwave-flash" width="100" height="75" data="http://www.flickr.com/apps/video/stewart.swf?v=1.172" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">'
		      + '<param name="flashvars" value="intl_lang=en-us&amp;photo_secret='+secret+'&amp;photo_id='+id+'"></param>'
		      + '<param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=1.172"></param>'
		      + '<param name="bgcolor" value="#000000"></param><param name="allowFullScreen" value="true"></param>'
		      + '<embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/video/stewart.swf?v=1.172" bgcolor="#000000"'
		           + 'allowfullscreen="true" flashvars="intl_lang=en-us&amp;photo_secret='+secret+'&amp;photo_id='+id+'" height="75" width="100"></embed></object>';
	}
	var genPhotoPageUrl = function( photoObj ){
		return 'http://www.flickr.com/photos/'+ photoObj.owner+'/'+ photoObj.id+'/';
	}
	var genUserTopUrl = function( user_id ){
		return 'http://www.flickr.com/photos/'+user_id+'/';
	}
	var genUserSetListPage = function( user_id ){
		return 'http://www.flickr.com/photos/'+user_id+'/sets/';
	}
	var genPhotoSetThumbnailUrl = function( photosetObj ){
		return 'http://farm'+photosetObj.farm+'.static.flickr.com/'+photosetObj.server+'/'+photosetObj.primary+'_'+photosetObj.secret+'_s.jpg';
	}
	var genPhotoSetUrl = function( photosetObj, user_id ){
		return 'http://www.flickr.com/photos/'+user_id+'/sets/'+photosetObj.id+'/';
	}
	var genContactIconImgUrl = function( contactObj ){
		return ( contactObj.iconserver != 0 )
			? 'http://farm'+contactObj.iconfarm+'.static.flickr.com/'+contactObj.iconserver+'/buddyicons/'+contactObj.nsid+'.jpg'
			: 'http://l.yimg.com/www.flickr.com/images/buddyicon.jpg';
	}
	var genContactListPageUrl = function( user_id ){
		return 'http://www.flickr.com/people/'+user_id+'/contacts/';
	}
	var genUserProfilePageUrl = function( user_id ){
		return 'http://www.flickr.com/people/'+user_id+'/';
	}
	
	/**** XHR utility functions ************************************************/
	var eval_jsonp = function( res ){
		if( res.status != 200 ) return;
		eval( res.responseText );
	};
	
	var genHttpRequestObj = function( url, callback ){
		return {
			method: 'GET',
			url: url,
			onload: callback
		};
	};
	
	/**** Other Functions ******************************************************************/
	var tieUpFlickrUsername = function(){
		friend_username = document.getElementById('flickrfriendusername').value;
		if( !friend_username ){
			friendinfo.clear(friend_key);
			friendinfo.write();
			alert("連携をやめました");
			location.reload();
			return;
		}
		var url = flickr_entrypoint + "method=flickr.people.findByUsername"
		          + "&api_key="+api_key+"&username="+friend_username+"&format=json&jsoncallback=setFriendUserId";
		GM_xmlhttpRequest( genHttpRequestObj( url, eval_jsonp ) );

	}
	/***********************************************************************/
	var pre_main = function(){
		
		if( !(yid = getYid()) ) 
			return false;
		
		api_key = userinfo.get('api_key');
		if( !api_key ){
			api_key = prompt("input your Flickr API key");
			if( !api_key ) return false;
			userinfo.set('api_key', api_key );
			userinfo.write();
		}

		username = userinfo.get('username');
		if( !username ){
			username = prompt("input your Flickr username");
			if( !username ) return false;
			userinfo.set('username',username);
			userinfo.write();
		}
		user_id = userinfo.get('user_id');
		if( !user_id ){
			var url = flickr_entrypoint + "method=flickr.people.findByUsername"
			          + "&api_key="+api_key+"&username="+username+"&format=json&jsoncallback=setUserId";
			GM_xmlhttpRequest( genHttpRequestObj( url, eval_jsonp ) );
		}
		return true;
		
	}

	var retryMax = 5;
	var retry = 0;
	var call_main_if_user_id_is_loaded = function(){
		if( user_id ){
			main();
			return;
		}
		if( retry++ < retryMax )
			setTimeout( call_main_if_user_id_is_loaded, 1000 );
	}

	var show_flickr_images_on_sub = function( id ){
		var target = findElementsByXpath('//div[@id="sub"]/div[@class="moduleTypeM"]').snapshotItem(0);
		var div1 = createNode('div', 'myPhoto moduleTypeM');
		div1.id = 'flickrphotos';
		var div2 = createNode('div', 'myPhoto moduleTypeM');
		div2.id = 'flickrsets';
		target.parentNode.insertBefore( div1, target );
		target.parentNode.insertBefore( div2, target );
		url = flickr_entrypoint + "method=flickr.people.getPublicPhotos"
		          + "&api_key="+api_key+"&user_id="+id+"&per_page=5&extras=farm,media&format=json&jsoncallback=showFlickrPhotos";
		GM_xmlhttpRequest( genHttpRequestObj( url, eval_jsonp ) );
		url = flickr_entrypoint + "method=flickr.photosets.getList"
		          + "&api_key="+api_key+"&user_id="+id+"&format=json&jsoncallback=showFlickrSets";
		GM_xmlhttpRequest( genHttpRequestObj( url, eval_jsonp ) );
		url = flickr_entrypoint + "method=flickr.contacts.getPublicList"
		          + "&api_key="+api_key+"&user_id="+id+"&per_page=9&format=json&jsoncallback=showFlickrContact";
		GM_xmlhttpRequest( genHttpRequestObj( url, eval_jsonp ) );
	}
	
	var show_friends_flickr_profile_link = function(){
		var target = findElementsByXpath('//div[@id="sub"]//span[@class="nameContainer"]/strong');
		var len = target.snapshotLength;
		for( var i = 0; i < len; i++ ){
			var node = target.snapshotItem(i);
			node.getElementsByTagName('a')[0].getAttribute('href').match(/profile-(.*)$/);
			var friend_key = RegExp.$1;
			var user = friendinfo.get( friend_key );
			node.innerHTML = '<img src="http://www.yahoo.co.jp/favicon.ico" /> ' + node.innerHTML;
			if( !user )
				continue;
			node.innerHTML += '<br /><img src="http://flickr.com/favicon.ico"/> <a href="'+genUserProfilePageUrl(user.id)+'">'+user.username+'</a>';
		}
	}
	
	var main = function(){
		var url = "";
		showFlickrMasthead();
		createTab();
		if( now_url == 'http://album.yahoo.co.jp/' ){
			var target = findElementsByXpath('//div[@id="main"]/div[@class="friendNewPhoto moduleTypeM"]').snapshotItem(0);
			var div1 = createNode('div', 'friendNewPhoto moduleTypeM');
			div1.id = 'flickrinterestingness';
			var div2 = createNode('div', 'friendNewPhoto moduleTypeM');
			div2.id = 'flickrcontactphoto';
			target.parentNode.insertBefore( div1, target );
			target.parentNode.insertBefore( div2, target );

			url = flickr_entrypoint + "method=flickr.photos.getContactsPublicPhotos"
			          + "&api_key="+api_key+"&user_id="+user_id+"&count=5&extras=farm,media&format=json&jsoncallback=showContactPhotos";
			GM_xmlhttpRequest( genHttpRequestObj( url, eval_jsonp ) );
			url = flickr_entrypoint + "method=flickr.interestingness.getList"
			          + "&api_key="+api_key+"&per_page=5&extras=farm,media&format=json&jsoncallback=showInterestingness";
			GM_xmlhttpRequest( genHttpRequestObj( url, eval_jsonp ) );
		}
		else if ( now_url == 'http://album.yahoo.co.jp/photos/my/' ){
			show_flickr_images_on_sub( user_id );
		}
		else if ( now_url.match( /^http:\/\/album\.yahoo\.co\.jp\/(?:profile-.*|photos\/my\/\d+\/)$/ ) ) {
			var target = findElementsByXpath('//form[@action="http://profiles.yahoo.co.jp/-/userbadge/redirect/"]/input[@name="target"]').snapshotItem(0);
			friend_key = target.value;
			friend_username = friendinfo.get(friend_key,'username') || "";
			friend_id = friendinfo.get(friend_key,'id') || "";
			target = findElementsByXpath('//div[@id="yahooIdentityUserCard"]/div[@class="roundCornerBox"]/div[@class="roundCornerMiddle"]'
			                                  + '/div[@class="roundCornerBox"]/div[@class="roundCornerMiddle"]/div[@class="yahooIdentityUserCardContents"]'
			                                  + '/div[@class="clearFix"]' ).snapshotItem(0);
			target.innerHTML += '<br />Flickr username:<input id="flickrfriendusername" type="text" size="10" value="'+friend_username+'"/>';
			var button = document.createElement('input');
			button.setAttribute('type','button');
			button.setAttribute('value','連携');
			button.addEventListener('click', tieUpFlickrUsername, false );
			target.appendChild( button );
			
			if( !friend_id ) 
				return;
				
			show_flickr_images_on_sub( friend_id );
		}
		else if ( now_url.match( /^http:\/\/album\.yahoo\.co\.jp\/friends\// ) ){
			show_friends_flickr_profile_link();
		}
	}

	/******* body of this Greasemonkey ****************/
	if( !pre_main() ){
		return;
	}
	call_main_if_user_id_is_loaded();


})();